home *** CD-ROM | disk | FTP | other *** search
/ Windows 6-Pak - Disc 5 / Windows 6-Pak (InfoMagic) (Disc 5) (1999).ISO / JAVA-Programming-Tools / apirc-1.1.exe / aprelay / aprelay.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-29  |  8.0 KB  |  379 lines

  1. /********************************************************/
  2. /*                   aprelay.c v1.2                     */
  3. /*             P.Toilon (zorthrax@id-net.fr)            */
  4. /*           29/10/1998 IDNET - Nancy - FRANCE          */
  5. /*    This relay is released into the Public Domain     */
  6. /*    The original file 'aprelay.c' has 8141 bytes      */
  7. /********************************************************/
  8.  
  9. /*
  10. ** This relay is made for Apirc v1.1
  11. ** IT WILL NOT WORK ON PREVIOUS VERSIONS
  12. */
  13.  
  14. #include <stdio.h>
  15. #include <netdb.h>
  16. #include <sys/time.h>
  17. #include <sys/socket.h>
  18. #include <netinet/in.h>
  19.  
  20. /* Change it to #undef UNIX if under Windows */
  21. #undef  UNIX
  22. /* Max simultaneous users on the relay */
  23. #define        MAXUSERS    128
  24.  
  25. /* Local listener socket timeout in seconds */
  26. #define        LCTIMEOUT    120
  27. /* Max length of negociation frame before connecting to remote */
  28. #define        MAXFRAME    128
  29. /* Max length of each frame's field */
  30. #define        MAXSE        (MAXFRAME/2)
  31.  
  32. /*
  33. ** Change CLASSIDENT to #define if :
  34. ** 1 - You want to have each user with a different username to
  35. **     avoid K-line on some servers.
  36. ** 2 - #define UNIX is set (and you are running a Unix/Linux OS)
  37. ** 3 - You can have root access and can set the aprelay file uid bit to root
  38. **     (under root, after each compilation, do a 'chmod u+s aprelay')
  39. ** On Windows OSes, you can run apidentd for this.
  40. */
  41. #ifdef UNIX
  42.  #define CLASSIDENT
  43. #endif
  44.  
  45. /*
  46. ** If CLASSIDENT is defined (see above), we set a range of UIDs
  47. ** that begin at FIRSTUID. For example if FIRSTUID = 3000 and
  48. ** MAXUSERS = 16, users will have 3000@yourmachine.com, 3001@
  49. ** yourmachine.com and so on until 3015.
  50. **
  51. ** As numbers could not be appreciated by some ircops, it's
  52. ** probably better to add corresponding login entries in
  53. ** /etc/passwd to get real names.
  54. **
  55. ** E.g.: Still with MAXUSERS = 16 and FIRSTUID = 3000, you
  56. ** should have to add 16 users on your system, from
  57. ** apircuser1 to apircuser16 with UIDs from 3000 to 3015
  58. ** (Full Name: "Untrusted chat user").
  59. **
  60. ** On RedHat 5.0 you should make : adduser -u 3000 apircuser1
  61. ** On Slackware, run adduser and follow the instructions.
  62. ** Do not edit directly /etc/passwd if shadow passwords are used.
  63. **
  64. ** Users will have apircuser1@yourmachine.com for example.
  65. ** If user addresses still remain with UID numbers, verify that
  66. ** the auth port 113 (identd) is reachable from outside.
  67. */
  68. #ifdef CLASSIDENT
  69.  #define FIRSTUID 3000
  70.  #define LASTUID (MAXUSERS+FIRSTUID-1)
  71. #endif
  72.  
  73. struct usr
  74. {
  75.     int fd;
  76.     int fdo;
  77. }    usr[MAXUSERS];
  78.  
  79. fd_set rfds,fds;
  80. long uip[MAXUSERS];
  81. struct sockaddr_in uin;
  82. short eoframe[MAXUSERS];
  83. int FIRST,mfd,maxfd,osz;
  84. char hname[MAXUSERS][MAXFRAME];
  85. char cnick[MAXSE],cserv[MAXSE],cport[MAXSE];
  86. char oc[BUFSIZ],*arg,*strchr(),*inet_ntoa(),tmp[BUFSIZ];
  87.  
  88. int open_remote_server_socket(server,port)
  89. char *server;
  90. int port;
  91. {
  92.     int fd;
  93.     struct hostent *rmt;
  94.     struct sockaddr_in out;
  95.  
  96.     if((fd=socket(AF_INET,SOCK_STREAM,0))<0)
  97.         return(-1);
  98.  
  99.     if(!(rmt=gethostbyname(server)))
  100.     {
  101.         close(fd);
  102.         return(-1);
  103.     }
  104.  
  105.     memcpy(&out.sin_addr,rmt->h_addr,rmt->h_length);
  106.  
  107.     out.sin_family=AF_INET;
  108.     out.sin_port=htons(port);
  109.  
  110.     if(connect(fd,(struct sockaddr *)&out,sizeof out)<0)
  111.     {
  112.         close(fd);
  113.         return(-1);
  114.     }
  115.  
  116.     return(fd);
  117. }
  118.  
  119. int open_listener_socket(port,maxusers,timeout)
  120. int port,maxusers,timeout;
  121. {
  122.     time_t tvey;
  123.     struct sockaddr_in in;
  124.     int fd,rt,sz=sizeof(struct sockaddr_in);
  125.  
  126.     if((fd=socket(AF_INET,SOCK_STREAM,0))<0)
  127.         return(-1);
  128.  
  129.     memset(&in,0,sz);
  130.     in.sin_family=AF_INET;
  131.     in.sin_addr.s_addr=INADDR_ANY;
  132.     in.sin_port=htons(port);
  133.  
  134.     time(&tvey);
  135.  
  136.     while((rt=bind(fd,(struct sockaddr *)&in,sz))<0 && (time(0l)-tvey)<timeout)
  137.         sleep(1);
  138.  
  139.     if(rt<0 || listen(fd,maxusers)<0)
  140.     {
  141.         close(fd);
  142.         return(-1);
  143.     }
  144.  
  145.     return(fd);
  146. }
  147.  
  148. int sd(fd,str)
  149. int fd;
  150. char *str;
  151. {
  152.     return(send(fd,str,strlen(str),0));
  153. }
  154.  
  155. int getnewusernum()
  156. {
  157.     int i;
  158.  
  159.     for(i=0;i<MAXUSERS;i++)
  160.         if(usr[i].fd==-1)
  161.             return(i);
  162.     return(-1);
  163. }
  164.  
  165. int getmaxfdvalue(fd)
  166. int fd;
  167. {
  168.     int i,j;
  169.  
  170.     for(i=0,j=-1;i<MAXUSERS;i++)
  171.     {
  172.         if(usr[i].fd>j)
  173.             j=usr[i].fd;
  174.         if(usr[i].fdo>j)
  175.             j=usr[i].fdo;
  176.     }
  177.  
  178.     if(fd>j)
  179.         j=fd;
  180.  
  181.     return(j);
  182. }
  183.  
  184. /*
  185. ** accept sent a broken pipe (signal 13)
  186. ** We go back into accept_user()
  187. */
  188. void b_accept()
  189. {
  190.     FIRST=0;
  191.     accept_user();
  192. }
  193.  
  194. accept_user()
  195. {
  196.     char *pt1,*pt2;
  197.     struct hostent *ht;
  198.     int i,j,si[4],newfd;
  199.  
  200.     /*
  201.     ** To avoid the accept() brokenpipe
  202.     */
  203.     signal(13,b_accept);
  204.  
  205.     if(FIRST)
  206.     {
  207.         for(i=0;i<MAXUSERS;i++)
  208.         {
  209.             usr[i].fd=-1;
  210.             usr[i].fdo=-1;
  211.         }
  212.  
  213.         FD_ZERO(&fds);
  214.         FD_ZERO(&rfds);
  215.         FD_SET((maxfd=mfd),&fds);
  216.     }
  217.  
  218.     while(1)
  219.     {
  220.         rfds=fds;
  221.         select(maxfd+1,&rfds,NULL,NULL,0);
  222.  
  223.         if(FD_ISSET(mfd,&rfds))
  224.         {
  225.             if((newfd=accept(mfd,(struct sockaddr *)&uin,&osz))>=0)
  226.             {
  227.                 /*
  228.                 ** IP Filtering. E.g: 'arg="192.168";' will
  229.                 ** forbid all 192.168.x.x IP addresses.
  230.                 */
  231.                 //arg="192.168.0.43";
  232.                 if(arg && !strncmp(arg,inet_ntoa(uin.sin_addr.s_addr),strlen(arg)))
  233.                 {
  234.                     sd(newfd,"Sorry, your host is not allowed !\n\r");
  235.                     close(newfd);
  236.                 }
  237.                 else if((i=getnewusernum())==-1)
  238.                 {
  239.                     sd(newfd,"Sorry, all relay sockets are busy !\n\r");
  240.                     close(newfd);
  241.                 }
  242.                 else
  243.                 {
  244.                     usr[i].fd=newfd;
  245.                     usr[i].fdo=-1;
  246.                     eoframe[i]=0;
  247.                     sd(usr[i].fd,"Apirc relay v1.2\r\n\n");
  248.                     if(!(ht=gethostbyaddr((char *)&uin.sin_addr,sizeof(unsigned long),AF_INET)))
  249.                         strcpy(hname[i],inet_ntoa(uin.sin_addr.s_addr));
  250.                     else
  251.                         strcpy(hname[i],ht->h_name);
  252.                     FD_SET(usr[i].fd,&fds);
  253.                     maxfd=getmaxfdvalue(mfd);
  254.                 }
  255.             }
  256.         }
  257.         else for(i=0;i<MAXUSERS;i++)
  258.         {
  259.             if(usr[i].fd!=-1 && FD_ISSET(usr[i].fd,&rfds))
  260.             {
  261.                 if(!(j=recv(usr[i].fd,oc,BUFSIZ,0)))    /* If disconnected */
  262.                 {
  263.                     FD_CLR(usr[i].fd,&fds);
  264.                     close(usr[i].fd);
  265.                     usr[i].fd=-1;
  266.                     if(usr[i].fdo!=-1)
  267.                     {
  268.                         FD_CLR(usr[i].fdo,&fds);
  269.                         close(usr[i].fdo);
  270.                         usr[i].fdo=-1;
  271.                     }
  272.                     maxfd=getmaxfdvalue(mfd);
  273.                 }
  274.                 else if(usr[i].fdo!=-1)    /* connected to remote serv */
  275.                     send(usr[i].fdo,oc,j,0);
  276.                 else if(!eoframe[i])
  277.                 {
  278.                     /* too big negociation frame */
  279.                     if(j>=MAXFRAME)
  280.                     {
  281.                         FD_CLR(usr[i].fd,&fds);
  282.                         close(usr[i].fd);
  283.                         usr[i].fd=-1;
  284.                         maxfd=getmaxfdvalue(mfd);
  285.                     }
  286.                     else if(j>4 && strchr(oc,'º')) /* "MyNick:irc.id-net.fr:6667:º" */
  287.                     {
  288.                         pt1=oc;
  289.                         *(pt2=strchr(pt1,':'))='\0';
  290.                         strcpy(cnick,pt1);
  291.                         pt1=pt2+1;
  292.                         *(pt2=strchr(pt1,':'))='\0';
  293.                         strcpy(cserv,pt1);
  294.                         pt1=pt2+1;
  295.                         *(pt2=strchr(pt1,':'))='\0';
  296.                         strcpy(cport,pt1);
  297.                         eoframe[i]=1;
  298.                     }
  299.                 }
  300.                 else    /* We just received the complete frame, let's connect */
  301.                 {
  302. #ifdef CLASSIDENT
  303.                     setreuid(FIRSTUID+i,NULL);
  304. #endif
  305.                     if((usr[i].fdo=open_remote_server_socket(cserv,atoi(cport)))<0)
  306.                     {
  307.                         sd(usr[i].fd,"Server unavailable\r\n");
  308.                         FD_CLR(usr[i].fd,&fds);    /* On libere */
  309.                         close(usr[i].fd);
  310.                         usr[i].fd=-1;
  311.                         maxfd=getmaxfdvalue(mfd);
  312.                     }
  313.                     else
  314.                     {
  315.                         FD_SET(usr[i].fdo,&fds);
  316.                         maxfd=getmaxfdvalue(mfd);
  317.                         srand(time(0l));
  318.                         sprintf(tmp,"NICK %s\nUSER user%d host server :%s [Real user host]\n",cnick,rand()%9000+1000,hname[i]);
  319.                         sd(usr[i].fdo,tmp);
  320.                         send(usr[i].fdo,oc,j,0);    /* 1st datas sent to th server */
  321.                     }
  322.                 }
  323.             }
  324.  
  325.             if(usr[i].fdo!=-1 && FD_ISSET(usr[i].fdo,&rfds))
  326.             {
  327.                 if(!(j=recv(usr[i].fdo,oc,BUFSIZ,0)))    /* If disconnected */
  328.                 {
  329.                     FD_CLR(usr[i].fd,&fds);
  330.                     FD_CLR(usr[i].fdo,&fds);
  331.                     close(usr[i].fd);
  332.                     close(usr[i].fdo);
  333.                     usr[i].fd=-1;
  334.                     usr[i].fdo=-1;
  335.                     maxfd=getmaxfdvalue(mfd);
  336.                 }
  337.                 else
  338.                     send(usr[i].fd,oc,j,0);
  339.             }
  340.         }
  341.     }
  342. }
  343.  
  344. main(argc,argv)
  345. int argc;
  346. char **argv;
  347. {
  348.     arg=(argc==2)?argv[1]:NULL;
  349.  
  350. #ifdef CLASSIDENT
  351.     if(getuid() && setuid(NULL)==-1)
  352.     {
  353.         printf("\nYou must set the binary file uid bit to root. Daemon not ready\n");
  354.         exit();
  355.     }
  356. #endif
  357.  
  358.     printf("Trying to open the listener socket ... ");
  359.     fflush(stdout);
  360.  
  361.     if((mfd=open_listener_socket(8888,MAXUSERS,LCTIMEOUT))<0)
  362.     {
  363.         printf("\nSocket not openable. Daemon not ready\n");
  364.         exit();
  365.     }
  366.  
  367.     printf("\nListener socket ready\n");
  368.     fflush(stdout);
  369.  
  370. #ifdef UNIX
  371.     if(fork())
  372.         exit();
  373. #endif
  374.  
  375.     osz=sizeof(struct sockaddr_in);
  376.     FIRST=1;
  377.     accept_user();
  378. }
  379.